// tnxbsv.js
import tnxjq from '@truenewx/tnxcore/src/tnxjq';
import tnxvue from '../tnxvue.js';
import * as BootstrapVue from 'bootstrap-vue-next';
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap-vue-next/dist/bootstrap-vue-next.css';
import './tnxbsv.css';

import Alert from './alert/Alert.vue';
import Button from './button/Button.vue';
import Cascader from './cascader/Cascader.vue';
import Dialog from './dialog/Dialog.vue';
import EnumSelect from './enum-select/EnumSelect.vue';
import Form from './form/Form.vue';
import FormGroup from './form/FormGroup.vue';
import LoadingIcon from './loading-icon/LoadingIcon.vue';
import LoadingOverlay from './loading-overlay/LoadingOverlay.vue';
import Paged from './paged/Paged.vue';
import Progress from './progress/Progress.vue';
import QueryForm from './query-form/QueryForm.vue';
import QueryTable from './query-table/QueryTable.vue';
import RegionCascader from './region-cascader/RegionCascader.vue';
import Select from './select/Select.vue';
import SubmitForm from './submit-form/SubmitForm.vue';
import TagsInput from './tags-input/TagsInput.vue';
import Upload from './upload/Upload.vue';

export const build = tnxvue.build;

export default build('tnxbsv', () => {
    const components = Object.assign({}, tnxvue.components, {
        Alert,
        Button,
        Cascader,
        Dialog,
        EnumSelect,
        Form,
        FormGroup,
        LoadingIcon,
        Paged,
        Progress,
        QueryForm,
        QueryTable,
        RegionCascader,
        Select,
        SubmitForm,
        TagsInput,
        Upload,
    });

    const tnxbsv = Object.assign({}, tnxjq, tnxvue, {
        libs: Object.assign({}, tnxjq.libs, tnxvue.libs, {BootstrapVue}),
        components,
        componentDefaultApp: undefined, // 组件的默认app，从服务端获取数据的组件以此为远程请求的默认app
        dialogInstances: [], // 对话框堆栈
        dialog(content, title, buttons, options, contentProps) {
            // 弹出之前关闭所有加载框
            this.hideLoading();

            let id = new Date().getTime();
            let containerId = 'dialog-container-' + id;
            let componentDefinition = Object.assign({}, Dialog,);
            let rootProps = Object.assign({}, options, {
                modelValue: true,
                id: id,
                container: '#' + containerId,
                title,
                content,
                contentProps,
                buttons,
            });
            let dialogVm = window.tnx.createVueInstance(componentDefinition, null, rootProps);
            const dialogContainer = document.createElement('div');
            dialogContainer.className = 'tnxbsv-dialog-container';
            dialogContainer.id = containerId;
            document.body.appendChild(dialogContainer);
            let dialog = dialogVm.mount(dialogContainer);
            dialog.onHidden = this.util.function.after(dialog.onHidden, () => {
                dialogVm.unmount();
                window.tnx.dialogInstances.remove(dialog);
                document.body.removeChild(dialogContainer);
            });
            window.tnx.dialogInstances.push(dialog);
            return dialog;
        },
        closeDialog(all) {
            return new Promise((resolve) => {
                if (window.tnx.dialogInstances.length) {
                    let dialog = window.tnx.dialogInstances.pop();
                    while (dialog) {
                        const originalClose = dialog.close;
                        if (originalClose) {
                            dialog.close = function (cb) {
                                originalClose.call(this, () => {
                                    if (typeof cb === 'function') {
                                        cb();
                                    }
                                    resolve();
                                });
                            };
                            dialog.close();
                        } else {
                            resolve();
                        }

                        if (all) {
                            dialog = window.tnx.dialogInstances.pop();
                        } else {
                            break;
                        }
                    }
                } else {
                    resolve();
                }
            });
        },
        _closeMessage() {
            this.hideLoading();
            this.removeToast();
        },
        alert(message, title, options) {
            return new Promise(resolve => {
                let buttons = tnxvue.getDefaultDialogButtons('primary', close => {
                    return resolve(close);
                });
                message =
                    `<div class="tnxbsv-dialog-alert"><i class="bi bi-exclamation-circle-fill"></i><div>${message}</div></div>`;
                this.dialog(message, title, buttons, options);
            });
        },
        success(message, options) {
            return new Promise(resolve => {
                let buttons = tnxvue.getDefaultDialogButtons('primary', close => {
                    return resolve(close);
                });
                message =
                    `<div class="tnxbsv-dialog-success"><i class="bi bi-check-circle-fill"></i><div>${message}</div></div>`;
                this.dialog(message, '成功', buttons, options);
            });
        },
        error(message, options) {
            return new Promise(resolve => {
                let buttons = tnxvue.getDefaultDialogButtons('primary', close => {
                    return resolve(close);
                });
                message =
                    `<div class="tnxbsv-dialog-error"><i class="bi bi-x-circle-fill"></i><div>${message}</div></div>`;
                this.dialog(message, '错误', buttons, options);
            });
        },
        confirm(message, title = '确认', options) {
            return new Promise(resolve => {
                let buttons = tnxvue.getDefaultDialogButtons('confirm', yes => {
                    return resolve(yes);
                });
                message =
                    `<div class="tnxbsv-dialog-confirm"><i class="bi bi-question-circle-fill"></i><div>${message}</div></div>`;
                this.dialog(message, title, buttons, options);
            });
        },
        toast(message, timeout, options = {}) {
            this._closeMessage();

            const div = document.createElement('div');
            document.body.appendChild(div);

            return new Promise(resolve => {
                const Vue = window.tnx.libs.Vue;
                const ToastComponent = {
                    components: {
                        BToast: BootstrapVue.BToast
                    },
                    setup() {
                        const visible = Vue.ref(true);
                        Vue.onMounted(() => {
                            setTimeout(() => {
                                visible.value = false;
                                // 延迟移除组件，确保动画效果完成
                                setTimeout(() => {
                                    window.tnx.toastInstance?.unmount();
                                    try {
                                        document.body.removeChild(div);
                                    } catch (e) {
                                        // 忽略异常
                                    }
                                    resolve();
                                }, 500);
                            }, timeout || 1500);
                        });
                        return {visible};
                    },
                    render() {
                        return Vue.h(BootstrapVue.BToast, {
                            modelValue: this.visible,
                            variant: options.type || 'success',
                            static: true,
                            noCloseButton: true,
                            class: 'position-fixed',
                            style: {
                                top: '50%',
                                left: '50%',
                                transform: 'translate(-50%, -50%)',
                                zIndex: window.tnx.util.dom.minTopZIndex(),
                            }
                        }, () => message);
                    }
                };

                const instance = window.tnx.createVueInstance(ToastComponent);
                instance.mount(div);
                window.tnx.toastInstance = instance;
            });
        },
        removeToast() {
            if (window.tnx.toastInstance) {
                window.tnx.toastInstance.unmount();
                try {
                    document.body.removeChild(window.tnx.toastInstance._container);
                } catch (e) {
                    // 忽略异常
                }
                window.tnx.toastInstance = null;
            }
        },
        showLoading(message = '', options) {
            this._closeMessage();

            let div = document.createElement('div');
            div.classList.add('tnxbsv-loading-overlay')
            document.body.appendChild(div);
            let instance = window.tnx.createVueInstance(LoadingOverlay, null, {message});
            instance.mount(div);
            window.tnx.loadingInstances.push(instance);
            window.tnx.app.eventBus.emit('tnx.showLoading', options);
        },
        loadingInstances: [],
        hideLoading() {
            if (window.tnx.loadingInstances.length) {
                window.tnx.loadingInstances.forEach(instance => {
                    instance.unmount();
                });
                window.tnx.loadingInstances.length = 0;
                // 删除所有div.tnxbsv-loading-overlay
                document.body.querySelectorAll('div.tnxbsv-loading-overlay').forEach(div => {
                    document.body.removeChild(div);
                });
            }
        },
        closeLoading() {
            this.hideLoading();
        },
    });

    tnxbsv.install = tnxbsv.util.function.around(tnxbsv.install, function (install, vm) {
        install.call(tnxbsv, vm);
        vm.use(BootstrapVue.createBootstrap());
    });

    return tnxbsv;
});



